import Item from './Item'

const floorHeight = 84;// 地板宽度

const itemRate = {
  speed: 0.25,
  fly: 0.15,
  star: 0.6
}

export default class Floor extends Sprite {

  constructor() {
    super();

    this.maxRight = 0;// 剩余最大右边距离
    this.isOutComplete = false;// 是否通知外部出了边界

    this.itemList = [];// 道具列表

    this.autoSize = true;// 如果不开启autoSize floor的宽度和高度无法获取
  }

  /**
   * @method
   * 
   * @param {number} type - 1：游戏开始的完整地板；2：游戏进行中的随机地板
   */
  init(type) {

    this.isHit = false;
    this.isOutComplete = false;

    // 地板图片
    this.bgTexture = this.bgTexture ? this.bgTexture : Laya.loader.getRes("res/floor.png");

    // 计算xy位置
    this.x = Config.deviceWidth;// 放到设备右侧
    this.y = Config.deviceHeight - floorHeight * (1 + Math.round((Math.floor(Config.deviceHeight / floorHeight) - 1) * Math.random())) + 30;

    /**
     * # 绘制地板
     * - 留1个playerWH留给右边补齐
     * - 长度范围：2-9个人物宽度
     */
    this.bg = this.bg ? this.bg : new Sprite();
    this.bg.graphics.clear();
    const randomWidth = type === 1 ? (960 - Config.playerWH) : Config.playerWH * (2 + Math.round(Math.floor(960 / Config.playerWH - 2 - 1) * Math.random()));
    this.bg.graphics.drawTexture(Texture.createFromTexture(this.bgTexture, 0, 0, randomWidth , floorHeight), 0, 0, randomWidth, floorHeight);
    this.addChild(this.bg);

    // 补足地板右边部分
    this.rightBg = this.rightBg ? this.rightBg : new Sprite();
    this.rightBg.graphics.clear();
    this.rightBg.graphics.drawTexture(Texture.createFromTexture(this.bgTexture, Config.playerWH * (Math.floor(960 / Config.playerWH) - 1), 0, Config.playerWH, floorHeight), randomWidth, 0, Config.playerWH, floorHeight);
    this.addChild(this.rightBg);

    /**
     * # 两地板距离
     * 以简单为主，不作最大值获取判断。
     * 设定最小值，在判断不大于屏幕剩余距离 * 一定比例即可。
     */
    this.maxRight = Config.playerWH + (Config.deviceWidth - Config.playerWH) * Math.random();

    if(type === 2) this.addItem();

    Laya.timer.frameLoop(1, this, this.onLoop);
  }

  onLoop() {

    if(gamePauseHandle(this, this.onLoop)) return ;

    this.x -= Config.baseSpeed * 1.3;// 让地板的速度和移动比背景快一点
    if(!this.isOutComplete && ((this.x + this.width) < Config.deviceWidth - this.maxRight)) {// 出了边界，通知生成新的floor
      this.isOutComplete = true;
      this.event(Floor.OUT_COMPLETE, this);// 触发MapFloor 的 getFloor
    } else if((this.x + this.width) < 0) {// 判断整个floor是否不在屏幕里面了 如果不在了 就移除掉
      this.event(Floor.OUT_DIE, this);
    }
  }

  addItem() {

    const maxNum = Math.floor(this.width / Config.itemWH);// 计算一下道具最大数量 我们强制道具的宽度都是32
    const addNum = (maxNum > 5) ? (5 + Math.floor((maxNum - 5) * Math.random())) : maxNum;// 超过5个，就选5 ~ maxNum

    const sx = (this.width - addNum * Config.itemWH) / 2;// 第一个道具开始的x位置
    const arr = [];
    let specialItem = false;

    for(let i = 0; i < addNum; i++) {

      if(i % 2 === 0) continue ;// 每隔两个创建一次，即间隔调整

      // 查询一下当前物品列表里面是否有 有的话 就从里面拿
      const item = this.itemList.length > 0 ? this.itemList.shift() : Pool.getItemByClass("item", Item);
      item.visible = true;

      const itemRandNum = Math.random();
      // 是否有特殊物品 如果无 我们就生成特殊物品
      if(itemRandNum > (1 - itemRate.speed) && !specialItem) {
        specialItem = true;
        item.init(Item.ITEM_TYPE_SPEED);
      } else if (itemRandNum > (1 - itemRate.fly) && !specialItem) {
        specialItem = true;
        item.init(Item.ITEM_TYPE_FLY);
      } else {
        item.init(Item.ITEM_TYPE_STAR);
      }

      item.x = sx + i * Config.itemWH;
      item.pivotY = Config.grassHeight;

      this.addChild(item);
      arr.push(item);
    }

    // 存储当前所有item
    this.itemList = arr;
  }

  getItems() {
    return this.itemList;
  }

  /**
   * @method 踩地板
   * @desc 一开始没有再地板上面就不行了，即从地板下面上去是不可能的
   */
  checkHit(x, y) {
    // && y < (this.y + this.height)
    if(this.x - 20 < x && x < (this.x + this.width - 20)) {
      
      if(this.y < y && y < (this.y + this.height)) return true;// 在地板里，踩到地板了

      if(y < this.y) Config.currentFloory = 80;// 在地板上面
      else Config.currentFloory = this.y + this.height;// 在地板下面
      return false;
    }

    Config.currentFloory = 80;
    return false;
  }
}

//事件名称
//超过屏幕一定值出发新的floor事件
Floor.OUT_COMPLETE = 'floor_out_complete';
//整个地板都不在屏幕里面事件
Floor.OUT_DIE = 'floor_out_die';